package com.gt.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.regex.Pattern.compile;

/**
 * 常用工具包
 *
 * @author cxm
 * @since 2019-07-05
 */
public class CommonUtils {

    /**
     * 利用正则表达式判断字符串是否是数字
     * @param str
     * @return
     */
    public static boolean isNumeric(String str){
        Pattern pattern = compile("^[0-9]*$");
        Matcher isNum = pattern.matcher(str);
        if( !isNum.matches() ){
            return false;
        }
        return true;
    }

    /**
     * 手机号码验证
     *
     * @param str 手机号码
     * @return
     */
    public static boolean isMobile(final String str) {
        Pattern p = null;
        Matcher m = null;
        boolean b = false;
        String s2 = "^[1](([3|5|8][\\d])|([4][4,5,6,7,8,9])|([6][2,5,6,7])|([7][^9])|([9][1,8,9]))[\\d]{8}$";// 验证手机号
        if (StringUtils.isNotBlank(str)) {
            p = compile(s2);
            m = p.matcher(str);
            b = m.matches();
        }
        return b;
    }

    /**
     * 电话号码验证
     *
     * @param str 电话号码
     * @return 验证通过返回true
     */
    public static boolean isPhone(final String str) {
        Pattern p1 = null, p2 = null;
        Matcher m = null;
        boolean b = false;
        String str1 = "^[0][1-9]{2,3}-[0-9]{5,10}$";
        String str2 = "^[1-9]{1}[0-9]{5,8}$";
        // 验证带区号的
        p1 = compile(str1);
        // 验证没有区号的
        p2 = compile(str2);
        if (StringUtils.isNotBlank(str)) {
            if (str.length() > 9) {
                m = p1.matcher(str);
                b = m.matches();
            } else {
                m = p2.matcher(str);
                b = m.matches();
            }
        }
        return b;
    }

    /**
     * 判断不是电话号码和手机号码
     *
     * @param str 手机、电话号码
     * @return
     */
    public static boolean isNotTelPhone(final String str) {
        if (isMobile(str)) {
            return false;
        } else if (isPhone(str)) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 身份证验证
     *
     * @param idcard
     * @return
     */
    public static boolean isIdcard(final String idcard) {
        Pattern p = null;
        Matcher m = null;
        boolean b = false;
        String s2 = "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
        if (StringUtils.isNotBlank(idcard)) {
            p = compile(s2);
            m = p.matcher(idcard);
            b = m.matches();
        }
        return b;
    }

    public static boolean match(String idcard, String s2){
        Pattern p = null;
        Matcher m = null;
        boolean b = false;
        if (StringUtils.isNotBlank(idcard)) {
            p = compile(s2);
            m = p.matcher(idcard);
            b = m.matches();
        }
        return b;
    }

    /**
     * 验证是否非身份证
     *
     * @param idcard
     * @return
     */
    public static boolean isNotIdcard(final String idcard) {
        return false == isIdcard(idcard);
    }

    /**
     * 验证是否非身份证
     *
     * @param idcard
     * @return
     */
   /* public static boolean isNotIdcard(final String idcard, String cardType) {
        return false == isIdcard(idcard,cardType);
    }*/

    /**
     * 生成随机数字和字母
     *
     * @param length
     */
    public static final String RANDOM_CHAR = "char";
    public static final String RANDOM_NUM = "num";
    public static String getStringRandom(int length, String type) {
        String val = "";
        Random random = new Random();
        //参数length，表示生成几位随机数
        for (int i = 0; i < length; i++) {
            String charOrNum = "";
            if (StringUtils.isNotBlank(type) && (StringUtils.equals("char",type) || StringUtils.equals("num",type) ) ) {
                charOrNum = type;
            } else {
                charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            }
            //输出字母还是数字
            if ("char".equalsIgnoreCase(charOrNum)) {
                //输出是大写字母还是小写字母
                int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
                val += (char) (random.nextInt(26) + temp);
            } else if ("num".equalsIgnoreCase(charOrNum)) {
                val += String.valueOf(random.nextInt(10));
            }
        }
        return val;
    }

    /**
     * 手机号中间加*
     * @param num
     * @return
     */
    public static String coverPhone(String num) {
        if (StringUtils.isBlank(num)) {
            return "";
        }
        num = num.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
        return num;
    }

    public static String getStackTrace(Throwable throwable) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);

        try {
            throwable.printStackTrace(pw);
            return sw.toString();
        } finally {
            pw.close();
        }
    }
    /**
     * [身份证号] 前六位，后四位，其他用星号隐藏每位1个星号<例子:451002********1647>
     *
     * @param carId
     * @return
     */
    public static String idCard(String carId){
        if (StringUtils.isBlank(carId)) {
            return "";
        }
        return StringUtils.left(carId, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(carId, 4), StringUtils.length(carId), "*"), "******"));
    }
    /**
     * [银行卡号] 前六位，后四位，其他用星号隐藏每位1个星号<例子:6222600**********1234>
     *
     * @param cardNum
     * @return
     */
    public static String bankCard(String cardNum) {
        if (StringUtils.isBlank(cardNum)) {
            return "";
        }
        return StringUtils.left(cardNum, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), "******"));
    }

    /**
     * 金额分转元
     *
     * @param fen 金额（单位：分）
     * @return java.math.BigDecimal
     * @author linc
     */
    public static BigDecimal fenToYuan(BigDecimal fen) {
        return fen != null ? fen.divide(new BigDecimal("100"), 2, RoundingMode.UNNECESSARY).stripTrailingZeros() : null;
    }

    /**
     * 金额元转分
     *
     * @param yuan 金额（单位：元）
     * @return java.math.BigDecimal
     * @author linc
     */
    public static BigDecimal yuanToFen(BigDecimal yuan) {
        return yuan != null ? yuan.multiply(new BigDecimal("100")) : null;
    }

    /**
     * 统计文字个数（汉字算2个长度，其他算1个长度）
     *
     * @param str 文字
     * @return int
     * @author linc
     */
    public static int countStrLength(String str) {
        return countStrLength(str, 2, 1, 1, 1, 1);
    }

    /**
     * 统计文字个数
     *
     * @param str               文字
     * @param chineseLen        中文计算长度
     * @param englishLen        英文计算长度
     * @param blankLen          空格计算长度
     * @param numberLen         数字计算长度
     * @param otherCharacterLen 其他字符计算长度
     * @return int
     * @author linc
     */
    public static int countStrLength(String str, int chineseLen, int englishLen, int blankLen, int numberLen, int otherCharacterLen) {
        // 中文汉字的个数
        int chineseCount = 0;
        // 英文的个数
        int englishCount = 0;
        // 空格的个数
        int blankCount = 0;
        // 数字的个数
        int numberCount = 0;
        // 其他字符的个数
        int otherCharacterCount = 0;

        char[] charArrays = str.toCharArray();
        for (char charArray : charArrays) {
            if (Character.UnicodeBlock.of(charArray) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS) {
                //判断是否是中文汉字
                chineseCount += chineseLen;
                continue;
            }
            if ((charArray >= 65 && charArray <= 90) || (charArray >= 97 && charArray <= 122)) {
                //判断是否为英文字母, A-Z 65-90 a-z 97-122
                englishCount += englishLen;
                continue;
            }
            //空格的ascii码值是32
            if (charArray == 32) {
                blankCount += blankLen;
                continue;
            }
            //数字0~9对应的ASCII码范围为[48,57]
            if ((charArray >= 48 && charArray <= 57)) {
                //判断是否为数字
                numberCount += numberLen;
                continue;
            }
            //当不是中文汉字、英文字母、空格、数字时,那么就代表它是其他字符了
            otherCharacterCount += otherCharacterLen;
        }
        // 返回总个数
        return chineseCount + englishCount + blankCount + numberCount + otherCharacterCount;
    }

    /**
     * 返回错误提示
     *
     * @param msg 错误提示
     * @return com.alibaba.fastjson2.JSONObject
     * @author linc
     */
    public static JSONObject retData(String code, String msg) {
        JSONObject retData = new JSONObject();
        retData.put("code", code);
        retData.put("msg", msg);
        return retData;
    }
    /**
     * 姓名脱敏
     * @param name
     * @return
     */
    public static String desensitizeName(String name) {
        if (name.length() == 2) {
            return name.substring(0, 1) + "*";
        } else if (name.length() > 2) {
            StringBuilder sb = new StringBuilder(name);
            for (int i = 1; i <= name.length()-2; i++) {
                sb.setCharAt(i, '*');
            }
            return sb.toString();
        }
        return name;
    }

    public static List<Integer> array_diff(List<Integer> array1, List<Integer> array2) {
        Set<Integer> set = new HashSet<>();
        for (int num : array1) {
            set.add(num);
        }

        int diffSize = array1.size() + array2.size() - 2 * set.size();
        List<Integer> diff = new ArrayList<>();
        int index = 0;

//        for (int num : array2) {
        for (int i=0;i<array2.size();i++) {
            Integer num = array2.get(i);
            if (!set.contains(num)) {
                diff.add(num);
            }
        }
        return diff;
    }

    public static String[] getUrl(String url) {
        String regex = "^[^\\?+]\\?([\\w|\\W]+)=([\\w|\\W]*?)&([\\w|\\W]+)=([\\w|\\W]*?)$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(url);

        if (matcher.find()) {
            String[] res = new String[5];
            for (int i = 0; i < 5; i++) {
                res[i] = matcher.group(i);
            }
            return res;
        } else {
            return null;
        }
    }
}
